#include "ConnectionPool.h"
#include <iostream>
// 静态对象类外初始化
ConnectionPool *ConnectionPool::globalInstance = new ConnectionPool();

ConnectionPool::ConnectionPool()
{
    // 初始化数据库连接池
    if (!init("192.168.10.128", "root", "750923", "dragonim"))
    {
        printf("ConnectionPool init failed.\n");
        exit(1);
    }
}

ConnectionPool::~ConnectionPool()
{
    closePool();
}

bool ConnectionPool::init(const string &host, const string &user, const string &pwd, const string &dbName, int poolSize, int port)
{
    // 预先创建连接
    for (int i = 0; i < poolSize; i++)
    {
        MYSQL *mysql = nullptr;
        mysql = mysql_init(mysql);
        if (!mysql)
        {
            printf("mysql_init() failed.\n");
            return false;
        }
        mysql = mysql_real_connect(mysql, host.data(), user.data(), pwd.data(), dbName.data(), port, nullptr, 0);
        if (!mysql)
        {
            printf("mysql_real_connect() failed.\n");
            return false;
        }
        connQue.push(mysql);
    }
    m_poolSize = poolSize;
    return true;
}

MYSQL *ConnectionPool::getConnObj()
{
    if (connQue.empty())
    {
        printf("ConnectionPool busy.\n");
        return nullptr;
    }
    // 加锁,如果互斥量被其他线程锁住,则调用线程阻塞    try_lock():如果互斥量被其他线程锁住,则调用线程不会阻塞
    m_mutex.lock();
    // 取出一个连接
    MYSQL *mysql = connQue.front();
    connQue.pop();
    // 解锁
    m_mutex.unlock();

    return mysql;
}

void ConnectionPool::recycleConnObj(MYSQL *conn)
{
    // conn为无效连接 或 连接队列已满,则直接返回
    if (conn == nullptr || connQue.size() > (m_poolSize - 1))
        return;
    m_mutex.lock();
    connQue.push(conn);
    m_mutex.unlock();
}

void ConnectionPool::closePool()
{
    m_mutex.lock();
    while (!connQue.empty())
    {
        MYSQL *conn = connQue.front();
        connQue.pop();
        mysql_close(conn);
    }
    m_mutex.unlock();

    // 清理和释放库使用的资源
    mysql_library_end();
}
